/*
** Dis6502.h
** contains includes, macros, structures, global variables and prototypes.
*/

#include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <memory.h>
#include <io.h>
#include <direct.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys\stat.h>
#include "dumpctl.h"
#include "spritctl.h"
#include "disctl.h"
#include "compusys.h"
#include "resource.h"

#include "image.h"

/*
** macro definitions
*/
#define FONT_WIDTH       8
#define FONT_HEIGHT      8

#define SEGMENT_LEFT     DUMP_LEFT + 1
#define SEGMENT_TOP      (FONT_HEIGHT + 3)
#define SEGMENT_COL      DUMP_COL
#define SEGMENT_WIDTH    (DUMP_WIDTH - 2)
#define SEGMENT_LINES    8
#define SEGMENT_HEIGHT   (SEGMENT_LINES * FONT_HEIGHT)

#define DUMP_LEFT        0
#define DUMP_TOP         ((SEGMENT_TOP * 2) + SEGMENT_HEIGHT)
#define DUMP_COL         37
#define DUMP_WIDTH       ((DUMP_COL * FONT_WIDTH) + GetSystemMetrics(SM_CXVSCROLL) + 3)
#define DUMP_LINES       32
#define DUMP_HEIGHT      (DUMP_LINES * FONT_HEIGHT + 2)

#define DIS_LEFT         (SEGMENT_WIDTH + 2)
#define DIS_TOP          (SEGMENT_TOP - 1)
#define DIS_COL          37
#define DIS_WIDTH        ((DIS_COL * FONT_WIDTH) + GetSystemMetrics(SM_CXVSCROLL) + 3)
#define DIS_HEIGHT       (DUMP_TOP + DUMP_HEIGHT - DIS_TOP)
#define DIS_LINES        (DIS_HEIGHT / FONT_HEIGHT)

#define MAIN_WIDTH       (DIS_LEFT + DIS_WIDTH + 2)
#define MAIN_HEIGHT      (GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYCAPTION) + DIS_TOP + DIS_HEIGHT + 2)

#define MAX_DISASM       (LABEL_NUMBER + 1)    /* = 4 sections (3 label sections + 1 code section) */
#define MAX_BUF_LABEL    32500
#define MAX_PATCHES      40
#define MAX_SPY_ADDR     125
#define MAX_CONFIG_STRING_LNG 20

#define ID_SEGMENT       1000
#define ID_DUMP          1001
#define ID_DIS           1002

#define NO_DUMP          0xFFFF

#define SPY_LNG_SEC      363
#define SPY_PATCH_SEC    364
#define SPY_ADDR_SEC1    365
#define SPY_ADDR_SEC2    366
#define SPY_NUM_SEC1     367
#define SPY_NUM_SEC2     368
#define SPY_DATA_SEC     369
#define SPY_MAGIC        "SPY"

#define WM_OPENCMDLINE   WM_USER + 1248

#define IDM_DUMP_MENU              4321
#define IDM_DUMP_DISPLAY           (IDM_DUMP_MENU + 0)
#define IDM_DUMP_NO_DIS            (IDM_DUMP_MENU + 1)
#define IDM_DUMP_FIND_SPRITES      (IDM_DUMP_MENU + 2)
#define IDM_DUMP_SELECTALL         (IDM_DUMP_MENU + 3)
#define IDM_DUMP_FIND              (IDM_DUMP_MENU + 4)
#define IDM_DUMP_FIND_NEXT         (IDM_DUMP_MENU + 5)
#define IDM_DUMP_TYPE              (IDM_DUMP_MENU + 1000)
#define IDM_DUMP_TYPE_CODE         (IDM_DUMP_TYPE + DUMP_TYPE_CODE)
#define IDM_DUMP_TYPE_LOBYTE       (IDM_DUMP_TYPE + DUMP_TYPE_LOBYTE)
#define IDM_DUMP_TYPE_HIBYTE       (IDM_DUMP_TYPE + DUMP_TYPE_HIBYTE)
#define IDM_DUMP_TYPE_BYTE         (IDM_DUMP_TYPE + DUMP_TYPE_BYTE)
#define IDM_DUMP_TYPE_WORD         (IDM_DUMP_TYPE + DUMP_TYPE_WORD)
#define IDM_DUMP_TYPE_LABEL        (IDM_DUMP_TYPE + DUMP_TYPE_LABEL)
#define IDM_DUMP_TYPE_STRING       (IDM_DUMP_TYPE + DUMP_TYPE_STRING)
#define IDM_DUMP_TYPE_SBYTE        (IDM_DUMP_TYPE + DUMP_TYPE_SBYTE)
#define IDM_DUMP_TYPE_DLIST        (IDM_DUMP_TYPE + DUMP_TYPE_DLIST)
#define IDM_DUMP_TYPE_STORE        (IDM_DUMP_TYPE + DUMP_TYPE_STORE)

typedef enum
     {
     LABEL_SYSTEM = 0,
     LABEL_USER,
     LABEL_CODE,

     /*
     ** this is a marker to know how many label types there are.
     */
     LABEL_NUMBER
     } LABEL_ENUM;

typedef enum
     {
     LABEL_FLAG_UNREFERENCED = 0,
     LABEL_FLAG_REFERENCED,
     LABEL_FLAG_DEFINED
     } LABEL_FLAG;

typedef enum
     {
     COLOR_BK = 0,
     COLOR_PF1,
     COLOR_PF2,
     COLOR_PF3,

     /*
     ** this is a marker to know how many colors there are.
     */
     COLOR_NUMBER
     } COLOR_ENUM;

/*
** structures
*/
typedef struct CONFIG10
               {
               /* General */
               BYTE      szComment[MAX_CONFIG_STRING_LNG];
               BYTE      szHex[MAX_CONFIG_STRING_LNG];
               BOOL      bIllegalOpcodes;
               BOOL      bLineNumbering;
               BOOL      bAlignInstructions;
               BOOL      bUseHex;
               BOOL      bShowAforImplicite;
               /* Assembler syntax */
               BYTE      szBYTE[MAX_CONFIG_STRING_LNG];
               BYTE      szWORD[MAX_CONFIG_STRING_LNG];
               BYTE      szSBYTE[MAX_CONFIG_STRING_LNG];
               BYTE      szORG[MAX_CONFIG_STRING_LNG];
               BYTE      szEQU[MAX_CONFIG_STRING_LNG];
               BYTE      szENDHead[MAX_CONFIG_STRING_LNG];
               BYTE      szENDTail[MAX_CONFIG_STRING_LNG];
               BYTE      szLOWHead[MAX_CONFIG_STRING_LNG];
               BYTE      szLOWTail[MAX_CONFIG_STRING_LNG];
               BYTE      szHIGHHead[MAX_CONFIG_STRING_LNG];
               BYTE      szHIGHTail[MAX_CONFIG_STRING_LNG];
               BYTE      szByteSeparator[MAX_CONFIG_STRING_LNG];
               BOOL      bNumOnlyInByte;
               BOOL      bWordAllowed;
               BOOL      bSByteAllowed;
               BOOL      bEndNeedFilename;
               /* Include and object files */
               BYTE      szINCLUDEHead[MAX_CONFIG_STRING_LNG];
               BYTE      szINCLUDETail[MAX_CONFIG_STRING_LNG];
               WORD      wNbLinesPerInclude;
               BOOL      bOneMainFile;
               BOOL      bIncludeAllowed;
               } CONFIG10;

typedef struct CONFIG
               {
               /* configuration version 1.0 */
               CONFIG10  config10;
               /* Addition to assembler syntax */
               BYTE      szDS[MAX_CONFIG_STRING_LNG];
               BOOL      bDSAllowed;
               } CONFIG;

/*
** global variables
*/
#ifndef EXTERN
#define EXTERN extern
#endif

EXTERN HANDLE hInst;
EXTERN HWND hMainWnd;
EXTERN HWND hSegmentList;
EXTERN HWND hDumpWnd;
EXTERN HWND hDisWnd;
EXTERN HFONT hComputerFont;
EXTERN HINSTANCE hComputerInst;
EXTERN char szComputerName[20];
EXTERN char szComputerDll[_MAX_PATH];
EXTERN char szComputerEqu[_MAX_PATH];
EXTERN char szErr[1024];
EXTERN char szBinPath[_MAX_PATH];
EXTERN char szAtrPath[_MAX_PATH];
EXTERN char szSpyPath[_MAX_PATH];
EXTERN char *szBinName;
EXTERN char szTitleApp[80];
EXTERN char szSegmentTitle[80];
EXTERN char szNoSegmentTitle[80];
EXTERN char szDumpTitle[80];
EXTERN char szNoDumpTitle[80];
EXTERN char szDisassembly[80];
EXTERN SEGMENT Segment[MAX_SEGMENTS];
EXTERN DIS_BUFFER *Disasm[MAX_DISASM];
EXTERN WORD wDumpSegment;
EXTERN WORD wDumpBeginLine;
EXTERN WORD wDumpBeginCol;
EXTERN WORD wDumpEndLine;
EXTERN WORD wDumpEndCol;
EXTERN HMENU hDumpMenuPopup;
EXTERN HMENU hDumpSubMenuPopup;
EXTERN WORD wDisScroll;
EXTERN WORD wDisMaxScroll;
EXTERN WORD wDisIndex;
EXTERN BOOL bDisCancel;
EXTERN char *lpLabelUser;
EXTERN char *lpLabelSystem;
EXTERN WORD *lpLabelCode;
EXTERN WORD *lpLabelCodeNotUsed;
EXTERN int iDiskIndex;
EXTERN BYTE cReturn;
EXTERN BOOL bFontOK;

/*
** configuration variables.
*/
EXTERN CONFIG Config;                   /* assembler dependent configuration */
EXTERN WORD wConfigNbWordsPerLine;      /* number of words per line (in .WORD directive) */
EXTERN WORD wConfigNbBytesPerLine;      /* number of bytes per line (in .BYTE directive) */
EXTERN WORD wConfigNbCharPerString;     /* number of characters in strings */
EXTERN BOOL bConfigDumpInternal;        /* dump uses internal character set (ANTIC) */
EXTERN BOOL bConfigNoDisassembly;       /* no disassembly launched if byte type is changed */

/*
** computer specific entry points
*/
EXTERN COMPUINIT CompuInit;
EXTERN COMPUTERM CompuTerm;
EXTERN COMPUGETMENU CompuGetMenu;
EXTERN COMPULOADSEGMENT CompuLoadSegment;
EXTERN COMPUUPDATESEGMENT CompuUpdateSegment;
EXTERN COMPUREADFILE CompuReadFile;
EXTERN COMPUGETRETURN CompuGetReturn;

/*
** prototypes
*/
void Error(HWND hWnd, WORD wStringID, char *szDefault, ...);
BYTE *MemoryAlloc(WORD wSize);
BYTE *MemoryRealloc(BYTE *lpBuf, WORD wSize);
void MemoryFree(BYTE *lpBuf);
BOOL GetFileName(HWND hDlg, LPSTR lpszFileName, DWORD dwFlags, UINT uTitleRsc, LPSTR lpszFilter);
BOOL SaveFileName(HWND hDlg, LPSTR lpszFileName, DWORD dwFlags, UINT uTitleRsc, LPSTR lpszFilter);

char *LabelFindEquate(WORD wAddr, LABEL_FLAG *bFlag);
void LabelUserSetFlag(LABEL_FLAG bFlag);
void LabelFreeCode(void);
void LabelFreeUser(void);
void LabelInit(void);
void LabelTerm(void);
void LabelLoad(HANDLE hInstance, HWND hWnd);
BOOL LabelUserLoad(HANDLE hInstance, HWND hWnd);
void LabelUserSave(HANDLE hInstance, HWND hWnd);
BOOL LabelUserClear(HANDLE hInstance, HWND hWnd);
BOOL LabelUserEdit(HANDLE hInstance, HWND hWnd);
BOOL LabelAddCode(HWND hWnd, WORD wAddr, BOOL bCheckExist);
void LabelSortCode(void);
BOOL LabelDumpCode(HWND hWnd);
void LabelDeleteCodeUsed(WORD wAddr);
char *LabelFindCode(WORD wAddr);
char *LabelFind(WORD wAddr);
char *LabelReserve(WORD wAddr);
void LabelSaveUser(HWND hDlg, int fd);
void LabelRestoreUser(HWND hDlg, int fd);

void DumpRegister(HANDLE hInstance);
void DumpTerm(void);
void DumpChangeSegment(HWND hWnd);
void DumpDrawMenu(HWND hWnd);
void DumpSelChanged(HWND hWnd);
void DumpSprites(HWND hWnd);
void DumpDisassemble(HWND hWnd);
void DumpSetType(HWND hWnd, WORD wType);
void DumpReset(HWND hWnd);
void DumpSetInternal(HWND hWnd);
BOOL DumpFindString(HWND hWnd, char *szFindAscii, int nLength, BOOL bWholeFile);
BOOL DumpFindNextString(HWND hWnd);
BOOL DumpCanFind(BOOL bFirst);
void DumpGetFindParam(char *szFindAscii, int *nLength, BOOL *bWhole);
void DumpSelectAll(void);

void DisRegister(HANDLE hInstance);
BOOL DisAddLabel(HWND hWnd, char *szLabel, WORD wAddr, LABEL_ENUM wLabelType);
BOOL DisAddComment(HWND hWnd, char *szComment, LABEL_ENUM wLabelType);
void DisResetLabelLines(HWND hWnd);
void DisResetCodeLines(HWND hWnd);
void DisSelectLine(HWND hWnd, DWORD dwLineNumber, BOOL bRefresh);
void DisProcess(HANDLE hInstance, HWND hWnd);
void DisReset(HWND hWnd);
void DisRefresh(HWND hWnd);
BOOL DisIsImmediateMode(BYTE cOpcode);

void ConfigInit(void);
long ConfigOutputFormat(HWND hWnd);
long ConfigAsmFormat(HWND hWnd);

void WorkspaceLoad(HWND hWnd);
void WorkspaceSave(HWND hWnd);

long TransferFile(HWND hWnd);

void SegmentReset(HWND hWnd);
int SegmentGetFirstFree(void);
int SegmentGetCount(void);
void SegmentSelect(WORD wIndex);
void SegmentSelected(void);
void SegmentUpdate(void);

void RefreshToolsMenu(void);
void MainSetName(void);
void MainClean(BOOL bAskForReset);
